import 'dart:io';
import 'dart:typed_data';

import 'package:flutter_disk_lru_cache/flutter_disk_lru_cache.dart';

class DiskLruCacheUtils {
  /// 工厂模式
  factory DiskLruCacheUtils() => _getInstance();

  /// 单例
  static DiskLruCacheUtils get instance => _getInstance();
  static DiskLruCacheUtils? _instance;

  /// 磁盘缓存
  late final DiskLruCache _diskLruCache;

  /// 是否初始化了
  bool _isInit = false;

  /// 是否写入过新的文件到磁盘缓存
  bool _isWriteFileToDisk = false;

  bool get isWriteFileToDisk => _isWriteFileToDisk;

  DiskLruCacheUtils._internal();

  static DiskLruCacheUtils _getInstance() => _instance ??= DiskLruCacheUtils._internal();

  /// 初始化磁盘缓存
  void open(
    Directory directory, {
    String version = "1.0.0",
    int valueCount = 1,
    int maxSize = 20 * 1024 * 1024,
  }) async {
    _diskLruCache = await DiskLruCache.open(directory, valueCount: valueCount, version: version, maxSize: maxSize);
    _isInit = true;
  }

  /// 获取一个图片key的数据
  Future<Uint8List?> getImageBytes(String key, [int index = 0]) async {
    if (!_isInit) return null;
    Snapshot? snapshot = await _diskLruCache.get(key);
    if (snapshot == null) {
      return null;
    }
    final Uint8List bytes = snapshot.getRandomAccessFile(index).readSync(snapshot.getLength(index));
    snapshot.close();
    return bytes;
  }

  /// 保存一个图片的key数据
  Future<Uint8List?> saveImageBytes(String key, Uint8List bytes, [int index = 0]) async {
    if (!_isInit) return null;
    Editor? editor = await _diskLruCache.edit(key);
    if (editor == null) {
      return null;
    }
    final FaultHidingIOSink faultHidingIOSink = editor.newOutputIOSink(index);
    await faultHidingIOSink.writeByte(bytes);
    faultHidingIOSink.close();
    editor.commit(_diskLruCache);
    _isWriteFileToDisk = true;
  }

  /// 刷新磁盘io
  Future<void> flush() async {
    if (!_isInit) return null;
    await _diskLruCache.flush().then((value) => _isWriteFileToDisk = false);
  }

  /// 关闭缓存
  Future<void> close() async {
    if (!_isInit) return null;
    _isInit = false;
    await _diskLruCache.close();
  }
}
